package com.autonavi.yunda.yunji.service;

import com.autonavi.yunda.yunji.common.exception.AmapException;
import com.autonavi.yunda.yunji.common.exception.AmapPreconditions;
import com.autonavi.yunda.yunji.domain.OrmTableParam;
import com.autonavi.yunda.yunji.core.enums.SqlOpEnum;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;

import static com.autonavi.yunda.yunji.constant.SqlConstants.*;

/**
 * @author by lufei on 2022-07-04.
 */

@Service
public class OrmTableService {

    private static final String delimiter = ",";

    public String getSql(OrmTableParam param) {
        OrmTableParam.Base base = param.getBase();
        String tb = base.getTb();
        String db = base.getDb();
        SqlOpEnum sqlOpEnum = base.getOp();
        if (StringUtils.isBlank(tb) || StringUtils.isBlank(db) || sqlOpEnum == null) {
            throw new AmapException("base param exception!");
        }
        String sql;
        switch (sqlOpEnum) {
            case SELECT:
                sql = selectSql(param);
                break;
            case UPDATE:
                sql = updateSql(param);
                break;
            case INSERT:
                sql = insertSql(param);
                break;
            case DELETE:
                sql = deleteSql(param);
                break;
            default:
                throw new AmapException("op exception!");
        }
        return sql;
    }

    private String getWhereStr(List<OrmTableParam.Where> whereFields) {
        if (CollectionUtils.isEmpty(whereFields)) {
            return "";
        }
        //where子句构造
        StringBuilder whereStr = new StringBuilder();
        whereStr.append(WHERE);
        for (int i = 0; i < whereFields.size(); i++) {
            OrmTableParam.Where where = whereFields.get(i);
            String field = where.getField();
            String condition = where.getCondition();
            String val = StringUtils.isBlank(where.getVal()) ? "$" + field : where.getVal();
            if (i > 0) {
                whereStr.append(AND);
            }
            whereStr.append(field).append(" ").append(condition).append(" '").append(val).append("'");
        }
        return whereStr.toString();
    }

    private String selectSql(OrmTableParam param) {
        //field 字段构造
        List<OrmTableParam.Field> fields = param.getField();
        StringBuilder fieldStr = new StringBuilder();
        if (!CollectionUtils.isEmpty(fields)) {
            for (int i = 0; i < fields.size(); i++) {
                if (i > 0) {
                    fieldStr.append(delimiter);
                }
                String field = fields.get(i).getField();
                fieldStr.append(field);
            }
        } else {
            fieldStr.append("*");
        }

        //where子句构造
        String whereStr = getWhereStr(param.getWhere());

        //order子句构造
        List<OrmTableParam.Order> orders = param.getOrder();
        StringBuilder orderStr = new StringBuilder();
        if (!CollectionUtils.isEmpty(orders)) {
            orderStr.append(ORDER_BY);
            orders.forEach(o -> {
                String field = o.getField();
                String orderType = o.getOrder();
                orderStr.append(field).append(" ").append(orderType);
            });
        }

        //limit子句构造
        StringBuilder pageStr;
        String start = "0";
        String offset = "10";
        if (param.getPage() != null) {
            start = StringUtils.isBlank(param.getPage().getStart()) ? start : param.getPage().getStart();
            offset = StringUtils.isBlank(param.getPage().getOffset()) ? offset : param.getPage().getOffset();
        }
        pageStr = new StringBuilder();
        pageStr.append(LIMIT).append(start).append(delimiter).append(offset);
        return SELECT +
                fieldStr +
                FROM +
                param.getBase().getTb() +
                whereStr +
                orderStr +
                pageStr + ";";
    }

    private String insertSql(OrmTableParam param) {
        //field 字段构造
        StringBuilder fieldStr = new StringBuilder();
        StringBuilder fieldVal = new StringBuilder();
        List<OrmTableParam.Field> fields = param.getField();
        AmapPreconditions.checkArgumentForUser(!CollectionUtils.isEmpty(fields), "操作字段列表不能为空");
        for (int i = 0; i < fields.size(); i++) {
            if (i > 0) {
                fieldStr.append(delimiter);
                fieldVal.append(delimiter);
            }
            String field = fields.get(i).getField();
            String val = StringUtils.isBlank(fields.get(i).getVal()) ? "'$" + field + "'" : "'" + fields.get(i).getVal() + "'";
            fieldStr.append(field);
            fieldVal.append(val);
        }
        return INSERT +
                param.getBase().getTb() +
                " (" + fieldStr + ")" +
                " values" + " (" + fieldVal + ")";

    }

    private String updateSql(OrmTableParam param) {
        String whereStr = getWhereStr(param.getWhere());
        if (StringUtils.isBlank(whereStr)) {
            throw new AmapException("update no where condition exception!");
        }
        //field 字段构造
        List<OrmTableParam.Field> fields = param.getField();
        AmapPreconditions.checkArgumentForUser(!CollectionUtils.isEmpty(fields), "操作字段列表不能为空");

        StringBuilder setVal = new StringBuilder();
        for (int i = 0; i < fields.size(); i++) {
            if (i > 0) {
                setVal.append(delimiter);
            }
            String field = fields.get(i).getField();
            String val = StringUtils.isBlank(fields.get(i).getVal()) ? "$" + field : fields.get(i).getVal();
            setVal.append(field).append("=").append("'").append(val).append("'");
        }
        return UPDATE +
                param.getBase().getTb() +
                SET +
                setVal +
                getWhereStr(param.getWhere());
    }

    private String deleteSql(OrmTableParam param) {
        //where子句构造
        String whereStr = getWhereStr(param.getWhere());
        AmapPreconditions.checkArgumentForUser(StringUtils.isNotBlank(whereStr), "delete no where condition exception!");
        return DELETE +
                FROM +
                param.getBase().getTb() +
                whereStr;
    }
}
